package com.lanhao.aot.carrierintegration.fedex;

import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aliyun.openservices.shade.com.alibaba.fastjson.JSON;
import com.fedex.shipment.Address;
import com.fedex.shipment.ClientDetail;
import com.fedex.shipment.CompletedPackageDetail;
import com.fedex.shipment.CompletedShipmentDetail;
import com.fedex.shipment.Contact;
import com.fedex.shipment.Dimensions;
import com.fedex.shipment.DropoffType;
import com.fedex.shipment.LabelFormatType;
import com.fedex.shipment.LabelSpecification;
import com.fedex.shipment.LabelStockType;
import com.fedex.shipment.LinearUnits;
import com.fedex.shipment.Notification;
import com.fedex.shipment.NotificationSeverityType;
import com.fedex.shipment.Party;
import com.fedex.shipment.Payment;
import com.fedex.shipment.PaymentType;
import com.fedex.shipment.Payor;
import com.fedex.shipment.PickupDetail;
import com.fedex.shipment.ProcessShipmentReply;
import com.fedex.shipment.ProcessShipmentRequest;
import com.fedex.shipment.RequestedPackageLineItem;
import com.fedex.shipment.RequestedShipment;
import com.fedex.shipment.ReturnShipmentDetail;
import com.fedex.shipment.ReturnType;
import com.fedex.shipment.ShipPortType;
import com.fedex.shipment.ShipService;
import com.fedex.shipment.ShipmentSpecialServicesRequested;
import com.fedex.shipment.ShippingDocument;
import com.fedex.shipment.ShippingDocumentImageType;
import com.fedex.shipment.ShippingDocumentPart;
import com.fedex.shipment.TransactionDetail;
import com.fedex.shipment.VersionId;
import com.fedex.shipment.WebAuthenticationCredential;
import com.fedex.shipment.WebAuthenticationDetail;
import com.fedex.shipment.Weight;
import com.fedex.shipment.WeightUnits;
import com.lanhao.aot.util.DateUtil;

/**
 * Call the FedEx Ship Service
 * 
 * @author kunzhou
 * @since 2020-11-28
 */
public class ShipWebServiceClient {
	private static final Logger LOG = LoggerFactory.getLogger(ShipWebServiceClient.class);
	// Other's Info
//	public static final String dev_accountNumber = "510087984";
//	public static final String dev_meterNumber = "118724827";
//	public static final String dev_key = "8fM8x9uNsUSLEIfO";
//	public static final String dev_password = "34ymdcY7vHEpBf347x9CClUXT";
	
	// Other's Info
//	public static final String prod_accountNumber = "275128910";
//	public static final String prod_meterNumber = "109395163";
//	public static final String prod_key = "AWTfEA4rkZ4FRsuq";
//	public static final String prod_password = "HHUIvYv3WBw7hseQNun2qw2iT";
	
	// My Info
	public static final String dev_accountNumber = "510088000";
	public static final String dev_meterNumber = "119181818";
	public static final String dev_key = "6KrKfJ2wnBit4XSK";
	public static final String dev_password = "H5t8kObM7tu8552OgyXUpEFNg";
	
	// My Info
	public static final String prod_accountNumber = "791094259";
	public static final String prod_meterNumber = "252653867";
	public static final String prod_key = "8YSW8vaegiiKnjDo";
	public static final String prod_password = "iL9n2hb1RWwcZsgFz2Q9W1dcE";
	

	public static String accountNumber = dev_accountNumber;
	public static String meterNumber = dev_meterNumber;
	public static String key = dev_key;
	public static String password = dev_password;

	public static final String ENV = "TEST";

	public static void main(String[] args) {

		if (ENV.equals("PROD")) {
			accountNumber = prod_accountNumber;
			meterNumber = prod_meterNumber;
			key = prod_key;
			password = prod_password;
		}

		ProcessShipmentRequest request = buildRequest();
		try {
			// Initialize the service
			ShipService service = new ShipService();
			ShipPortType port = service.getShipServicePort();
			ProcessShipmentReply reply = port.processShipment(request); // This is the call to the ship web service
			LOG.info("response={}", JSON.toJSONString(reply));
			// check if the call was successful
			if (isResponseOk(reply.getHighestSeverity())) {
				CompletedShipmentDetail csd = reply.getCompletedShipmentDetail();
				List<CompletedPackageDetail> cpd = csd.getCompletedPackageDetails();
				// Package details / Rating information for each package
				for (int i = 0; i < cpd.size(); i++) {
					CompletedPackageDetail cpdItem = cpd.get(i);
					String trackingNumber = cpdItem.getTrackingIds().get(i).getTrackingNumber();
					// Write label buffer to file
					ShippingDocument shippingDocument = cpdItem.getLabel();
					List<ShippingDocumentPart> sdparts = shippingDocument.getParts();
					if (CollectionUtils.isNotEmpty(sdparts)) {
						ShippingDocumentPart shippingDocumentPart = sdparts.get(0);
						byte[] image = shippingDocumentPart.getImage();
						String labelLocation = System.getProperty("file.label.location");
						if (labelLocation == null) {
							labelLocation = "D:\\";
						}
						String shippingDocumentType = shippingDocument.getType().value();
						String labelFileName = new String(labelLocation + shippingDocumentType + "_" + i + "."
								+ trackingNumber + "." + ShippingDocumentImageType.PDF);
						File labelFile = new File(labelFileName);
						FileOutputStream fos = new FileOutputStream(labelFile);
						fos.write(image);
						fos.close();
					}
				}
			} else {
				List<Notification> notifications = reply.getNotifications();
				if (CollectionUtils.isNotEmpty(notifications)) {
					Notification notification = notifications.get(0);
					String code = notification.getCode();
					String localizedMessage = notification.getLocalizedMessage();
					String message = notification.getMessage();
					LOG.info("获取标签失败，code={},localizedMessage={},message={}", code, localizedMessage, message);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static ProcessShipmentRequest buildRequest() {
		ProcessShipmentRequest request = new ProcessShipmentRequest(); // Build a request object

		ClientDetail clientDetail = new ClientDetail();
		clientDetail.setAccountNumber(accountNumber);
		clientDetail.setMeterNumber(meterNumber);
		request.setClientDetail(clientDetail);

		WebAuthenticationDetail webAuthenticationDetail = new WebAuthenticationDetail();
		WebAuthenticationCredential userCredential = new WebAuthenticationCredential();
		userCredential.setKey(key);
		userCredential.setPassword(password);
		webAuthenticationDetail.setUserCredential(userCredential);

		request.setWebAuthenticationDetail(webAuthenticationDetail);
		//
		TransactionDetail transactionDetail = new TransactionDetail();
		String transactionId = "AH-TR-" + System.currentTimeMillis();
		transactionDetail.setCustomerTransactionId(transactionId); // The client will get the same value back in the
																	// response
		request.setTransactionDetail(transactionDetail);

		VersionId versionId = new VersionId();
		versionId.setServiceId("ship");
		versionId.setMajor(26);
		versionId.setIntermediate(0);
		versionId.setMinor(0);
		request.setVersion(versionId);

		RequestedShipment requestedShipment = new RequestedShipment();
		requestedShipment.setShipTimestamp(DateUtil.convertToXMLGregorianCalendar(new Date())); // Ship date and time
		requestedShipment.setDropoffType(DropoffType.BUSINESS_SERVICE_CENTER); // Dropoff Types are BUSINESS_SERVICE_CENTER,
		requestedShipment.setServiceType("FEDEX_GROUND"); // Service types are STANDARD_OVERNIGHT, PRIORITY_OVERNIGHT, FEDEX_GROUND ...
//		requestedShipment.setServiceType("PRIORITY_OVERNIGHT");
		requestedShipment.setPackagingType("YOUR_PACKAGING"); // Packaging type FEDEX_BOX, FEDEX_PAK, FEDEX_TUBE, YOUR_PACKAGING, ...
		requestedShipment.setShipper(addShipper());
		requestedShipment.setRecipient(addRecipient());
		requestedShipment.setShippingChargesPayment(addShippingChargesPayment());
		// Example Shipment special service (Express COD).
		requestedShipment.setSpecialServicesRequested(addShipmentSpecialServicesRequested());
		
//		PickupDetail pickupDetail = new PickupDetail();
//		pickupDetail.setReadyDateTime(DateUtil.convertToXMLGregorianCalendar("2020-01-01 08:00:00"));
//		pickupDetail.setLatestPickupDateTime(DateUtil.convertToXMLGregorianCalendar("2020-12-31 18:00:00"));
//		requestedShipment.setPickupDetail(pickupDetail);
		
		LabelSpecification labelSpecification = new LabelSpecification(); // Label specification
		labelSpecification.setImageType(ShippingDocumentImageType.PDF);// Image types PDF, PNG, DPL, ...
		labelSpecification.setLabelFormatType(LabelFormatType.COMMON_2_D); // LABEL_DATA_ONLY, COMMON2D
		labelSpecification.setLabelStockType(LabelStockType.PAPER_4_X_6);
		requestedShipment.setLabelSpecification(labelSpecification);
		//
		requestedShipment.setPackageCount(new BigInteger("1"));
		requestedShipment.getRequestedPackageLineItems().add(addRequestedPackageLineItem());
		request.setRequestedShipment(requestedShipment);
		LOG.info("请求报文如下：request={}", JSON.toJSONString(request));
		return request;
	}

	private static boolean isResponseOk(NotificationSeverityType notificationSeverityType) {
		if (notificationSeverityType == null) {
			return false;
		}
		if (notificationSeverityType.equals(NotificationSeverityType.WARNING)
				|| notificationSeverityType.equals(NotificationSeverityType.NOTE)
				|| notificationSeverityType.equals(NotificationSeverityType.SUCCESS)) {
			return true;
		}
		return false;
	}

	private static Party addShipper() {
		Party shipperParty = new Party(); // Sender information
		Contact shipperContact = new Contact();
		shipperContact.setPersonName("Sharifah Alwasim");
		shipperContact.setCompanyName("");
		shipperContact.setPhoneNumber("3136990247");
		Address shipperAddress = new Address();
		shipperAddress.getStreetLines().add("8646 Dennison St");
		shipperAddress.setCity("Detroit");
		shipperAddress.setStateOrProvinceCode("MI");
		shipperAddress.setPostalCode("48210");
		shipperAddress.setCountryCode("US");
		shipperParty.setContact(shipperContact);
		shipperParty.setAddress(shipperAddress);
		return shipperParty;
	}

	private static Party addRecipient() {
		Party recipientParty = new Party(); // Recipient information
		Contact recipientContact = new Contact();
//		recipientContact.setPersonName("US-RTN-AE");
//		recipientContact.setCompanyName("");
//		recipientContact.setPhoneNumber("4085684260");
//		Address recipientAddress = new Address();
//		recipientAddress.getStreetLines().add("1424 Newbridge Ave, Sunny Island Group LLC");
//		recipientAddress.setCity("San Mateo");
//		recipientAddress.setStateOrProvinceCode("CA");
//		recipientAddress.setPostalCode("94401");
//		recipientAddress.setCountryCode("US");
//		recipientAddress.setResidential(Boolean.valueOf(false));
//		recipientParty.setContact(recipientContact);
//		recipientParty.setAddress(recipientAddress);
		
		recipientContact.setPersonName("US-RTN-AE");
		recipientContact.setCompanyName("");
		recipientContact.setPhoneNumber("9734623531");
		Address recipientAddress = new Address();
		recipientAddress.getStreetLines().add("57 Industrial Rd, Building B-A");
		recipientAddress.setCity("Berkeley Heights");
		recipientAddress.setStateOrProvinceCode("NJ");
		recipientAddress.setPostalCode("07922");
		recipientAddress.setCountryCode("US");
		recipientAddress.setResidential(Boolean.valueOf(false));
		recipientParty.setContact(recipientContact);
		recipientParty.setAddress(recipientAddress);
		
		
		return recipientParty;
	}

	private static Payment addShippingChargesPayment() {
		Payment payment = new Payment(); // Payment information
		payment.setPaymentType(PaymentType.SENDER);
		Payor payor = new Payor();
		Party responsibleParty = new Party();
		responsibleParty.setAccountNumber(accountNumber);
		Address responsiblePartyAddress = new Address();
		responsiblePartyAddress.setCountryCode("US");
		responsibleParty.setAddress(responsiblePartyAddress);
		responsibleParty.setContact(new Contact());
		payor.setResponsibleParty(responsibleParty);
		payment.setPayor(payor);
		return payment;
	}

	private static ShipmentSpecialServicesRequested addShipmentSpecialServicesRequested() {
		ShipmentSpecialServicesRequested shipmentSpecialServicesRequested = new ShipmentSpecialServicesRequested();
		shipmentSpecialServicesRequested.getSpecialServiceTypes().add("RETURN_SHIPMENT");
		
		ReturnShipmentDetail shipmentDetail = new ReturnShipmentDetail();
		shipmentDetail.setReturnType(ReturnType.PRINT_RETURN_LABEL);
		shipmentSpecialServicesRequested.setReturnShipmentDetail(shipmentDetail);
		
//		CodDetail codDetail = new CodDetail();
//		codDetail.setCollectionType(CodCollectionType.ANY);
//		Money codMoney = new Money();
//		codMoney.setCurrency("USD");
//		codMoney.setAmount(new BigDecimal(150.0));
//		codDetail.setCodCollectionAmount(codMoney);
//		shipmentSpecialServicesRequested.setCodDetail(codDetail);
		return shipmentSpecialServicesRequested;
	}

	private static RequestedPackageLineItem addRequestedPackageLineItem() {
		RequestedPackageLineItem requestedPackageLineItem = new RequestedPackageLineItem();
		requestedPackageLineItem.setSequenceNumber(new BigInteger("1"));
		requestedPackageLineItem.setGroupPackageCount(new BigInteger("1"));

		Weight weight = new Weight();
		weight.setUnits(WeightUnits.KG);
		weight.setValue(new BigDecimal(2.5));
		requestedPackageLineItem.setWeight(weight);

		Dimensions dimensions = new Dimensions();
		dimensions.setLength(new BigInteger("100"));
		dimensions.setWidth(new BigInteger("20"));
		dimensions.setHeight(new BigInteger("5"));
		dimensions.setUnits(LinearUnits.CM);
		requestedPackageLineItem.setDimensions(dimensions);

//		requestedPackageLineItem.getCustomerReferences().add(addCustomerReference(CustomerReferenceType.CUSTOMER_REFERENCE.value(), "CR1234"));
//		requestedPackageLineItem.getCustomerReferences().add(addCustomerReference(CustomerReferenceType.INVOICE_NUMBER.value(), "IV1234"));
//		requestedPackageLineItem.getCustomerReferences().add(addCustomerReference(CustomerReferenceType.P_O_NUMBER.value(), "PO1234"));

		return requestedPackageLineItem;
	}
	/**
	 * private static CustomerReference addCustomerReference(String
	 * customerReferenceType, String customerReferenceValue) { CustomerReference
	 * customerReference = new CustomerReference();
	 * customerReference.setCustomerReferenceType(CustomerReferenceType.fromValue(customerReferenceType));
	 * customerReference.setValue(customerReferenceValue); return customerReference;
	 * }
	 * 
	 * private static LabelSpecification addLabelSpecification() {
	 * LabelSpecification labelSpecification = new LabelSpecification(); // Label
	 * specification
	 * labelSpecification.setImageType(ShippingDocumentImageType.PDF);// Image types
	 * PDF, PNG, DPL, ...
	 * labelSpecification.setLabelFormatType(LabelFormatType.COMMON_2_D); //
	 * LABEL_DATA_ONLY, COMMON2D return labelSpecification; }
	 * 
	 * private static void saveLabelToFile(ShippingDocument shippingDocument, String
	 * trackingNumber) throws Exception { List<ShippingDocumentPart> sdparts =
	 * shippingDocument.getParts(); for (int a = 0; a < sdparts.size(); a++) {
	 * ShippingDocumentPart sdpart = sdparts.get(a); String labelLocation =
	 * System.getProperty("file.label.location"); if (labelLocation == null) {
	 * labelLocation = "D:\\"; } String shippingDocumentType =
	 * shippingDocument.getType().value(); String labelFileName = new String(
	 * labelLocation + shippingDocumentType + "." + trackingNumber + "_" + a + "." +
	 * ShippingDocumentImageType.PDF); File labelFile = new File(labelFileName);
	 * FileOutputStream fos = new FileOutputStream(labelFile);
	 * fos.write(sdpart.getImage()); fos.close(); System.out.println("\nlabel file
	 * name " + labelFile.getAbsolutePath()); Runtime.getRuntime().exec("rundll32
	 * url.dll,FileProtocolHandler " + labelFile.getAbsolutePath()); } } private
	 * static void saveShipmentDocumentsToFile(List<ShippingDocument>
	 * shippingDocument, String trackingNumber) throws Exception { if
	 * (shippingDocument != null) { for (int i = 0; i < shippingDocument.size();
	 * i++) { List<ShippingDocumentPart> sdparts =
	 * shippingDocument.get(i).getParts(); for (int a = 0; a < sdparts.size(); a++)
	 * { ShippingDocumentPart sdpart = sdparts.get(a); String labelLocation =
	 * System.getProperty("file.label.location"); if (labelLocation == null) {
	 * labelLocation = "D:\\"; } String labelName =
	 * shippingDocument.get(i).getType().value(); String
	 * shippingDocumentLabelFileName = new String( labelLocation + labelName + "." +
	 * trackingNumber + "_" + a + ".pdf"); File shippingDocumentLabelFile = new
	 * File(shippingDocumentLabelFileName); FileOutputStream fos = new
	 * FileOutputStream(shippingDocumentLabelFile); fos.write(sdpart.getImage());
	 * fos.close(); System.out.println( "\nAssociated shipment label file name " +
	 * shippingDocumentLabelFile.getAbsolutePath());
	 * Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " +
	 * shippingDocumentLabelFile.getAbsolutePath()); } } } }
	 * 
	 * private static void
	 * getAssociatedShipmentLabels(List<AssociatedShipmentDetail>
	 * associatedShipmentDetail) throws Exception { if (associatedShipmentDetail !=
	 * null) { for (int j = 0; j < associatedShipmentDetail.size(); j++) {
	 * AssociatedShipmentDetail associatedShipmentDetailItem =
	 * associatedShipmentDetail.get(j); if (associatedShipmentDetailItem.getLabel()
	 * != null && associatedShipmentDetailItem.getType() != null) { String
	 * trackingNumber =
	 * associatedShipmentDetailItem.getTrackingId().getTrackingNumber(); String
	 * associatedShipmentType = associatedShipmentDetailItem.getType().value();
	 * ShippingDocument associatedShipmentLabel =
	 * associatedShipmentDetailItem.getLabel();
	 * saveAssociatedShipmentLabelToFile(associatedShipmentLabel, trackingNumber,
	 * associatedShipmentType); } } } }
	 * 
	 * private static void saveAssociatedShipmentLabelToFile(ShippingDocument
	 * shippingDocument, String trackingNumber, String labelName) throws Exception {
	 * List<ShippingDocumentPart> sdparts = shippingDocument.getParts(); for (int a
	 * = 0; a < sdparts.size(); a++) { ShippingDocumentPart sdpart = sdparts.get(a);
	 * String labelLocation = System.getProperty("file.label.location"); if
	 * (labelLocation == null) { labelLocation = "D:\\"; } String
	 * associatedShipmentLabelFileName = new String( labelLocation + labelName + "."
	 * + trackingNumber + "_" + a + ".pdf"); File associatedShipmentLabelFile = new
	 * File(associatedShipmentLabelFileName); FileOutputStream fos = new
	 * FileOutputStream(associatedShipmentLabelFile); fos.write(sdpart.getImage());
	 * fos.close(); System.out .println("\nAssociated shipment label file name " +
	 * associatedShipmentLabelFile.getAbsolutePath()); Runtime.getRuntime()
	 * .exec("rundll32 url.dll,FileProtocolHandler " +
	 * associatedShipmentLabelFile.getAbsolutePath()); } }
	 **/

}
